package com.easytouch.core;

import android.os.SystemClock;
import android.text.TextUtils;

import com.easytouch.core.model.GoodsModel;
import com.easytouch.core.utils.FileTools;
import com.easytouch.core.utils.Log;
import com.easytouch.core.utils.PinYinUtils;

import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.ConcurrentModificationException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import static com.easytouch.core.Configure.DIRECTORY_CONFIG;

public class GoodsConfiguration {

    public final static String FILE_GOODS = "goods.xml";
    public final static String FILE_GOODS_DATABASE = "goodsDataBase.xml";
    private final static String TAG = "GoodsConfiguration.txt";

    private static ArrayList<GoodsModel> goodsList = new ArrayList<>(); // XML中所有的商品信息
    private static ArrayList<GoodsModel> goodsDataBaseList = new ArrayList<>(); // XML商品库

    private static final Object goodsListLock = new Object();
    private static final Object goodsDataBaseListLock = new Object();

    private static Log logger = null;

    private static Log getLogger() {
        if (logger == null) {
            logger = new Log("GoodsConfiguration.txt");
        }
        return logger;
    }

    /**
     * 读取商品配置
     */
    public static void loadGoodsXML() {
        if (Configure.context == null || Configure.path == null) {
            return;
        }
        clearGoodsList();
        String tempFile = "file://" + Configure.path + "/" + DIRECTORY_CONFIG + "/" + FILE_GOODS + "temp";
        String descFile = "file://" + Configure.path + "/" + DIRECTORY_CONFIG + "/" + FILE_GOODS;
        if (!loadGoodsXML(tempFile)) {
            loadGoodsXML(descFile);
        } else {
            FileTools.copyFile(tempFile, descFile);
        }
        loadGoodsDataBaseXML();
    }


    public static boolean loadGoodsXML(String file) {

        //实例化一个文档构建器工厂
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        try {
            //通过文档构建器工厂获取一个文档构建器
            DocumentBuilder db = dbf.newDocumentBuilder();
            //通过文档通过文档构建器构建一个文档实例
            Document doc = db.parse(file);
//            Document doc = db.parse("file://" + Configure.path + "/" + DIRECTORY_CONFIG + "/" + FILE_GOODS);
            NodeList nl1 = doc.getElementsByTagName("goods");
            if (nl1.getLength() == 0) {
                return false;
            }
            Node n1 = nl1.item(0);
            NodeList nl2 = n1.getChildNodes();
            if (nl2.getLength() == 0) {
                return false;
            }
            for (int i = 0; i < nl2.getLength(); i++) {
                Node n = nl2.item(i);
                if (!n.getNodeName().equals("item") || n.getNodeType() != Node.ELEMENT_NODE) {
                    continue;
                }
                NamedNodeMap map = n.getAttributes();
                if (map == null) {
                    continue;
                }
                Node NAME = map.getNamedItem("name");
                if (NAME == null) {
                    continue;
                }
                String name = NAME.getNodeValue();
//                Node CODE = map.getNamedItem("code"); //十进制
//                if (CODE == null) {
//                    continue;
//                }
//                String code = CODE.getNodeValue();
//                Node IMAGE = map.getNamedItem("image");
//                if (IMAGE == null) {
//                    continue;
//                }
//                String image = IMAGE.getNodeValue();
                Node TYPE = map.getNamedItem("type");
                if (TYPE == null) {
                    continue;
                }
                String type = TYPE.getNodeValue();
                Node BC = map.getNamedItem("bc");
                if (BC == null) {
                    continue;
                }
                String bc = BC.getNodeValue();
                Node DISCOUNT = map.getNamedItem("discount");
                String discount = "100";
                if (DISCOUNT != null) {
                    discount = DISCOUNT.getNodeValue();
                }

                Node WARRANTY = map.getNamedItem("warranty");
                String warranty = "0";
                if (WARRANTY != null) {
                    warranty = WARRANTY.getNodeValue();
                }
                Node EXPIRATION = map.getNamedItem("expiration");
                String expiration = "0";
                if (EXPIRATION != null) {
                    expiration = EXPIRATION.getNodeValue();
                }

                Node BOX = map.getNamedItem("box");
                if (BOX == null) {
                    continue;
                }
                String box = BOX.getNodeValue();

                Node COLUMN = map.getNamedItem("column");
                if (COLUMN == null) {
                    continue;
                }
                String column = COLUMN.getNodeValue();

                GoodsModel goods = new GoodsModel();
                goods.setName(name);
//                goods.setCode(code != null ? code : "");
//                goods.setImage(image);
                goods.setType(type);
                goods.setBarCode(bc != null ? bc : "");
                try {
                    int dis = Integer.parseInt(discount);
                    int war = Integer.parseInt(warranty);
                    int exp = Integer.parseInt(expiration);
                    if (dis < 1) {
                        dis = 1;
                    } else if (dis > 1000) {
                        dis = 1000;
                    }
                    if (war < 0) {
                        war = 0;
                    }
                    if (exp < 0) {
                        exp = 0;
                    }
                    goods.setDiscount(dis);
                    goods.setWarranty(war);
                    goods.setExpiration(exp);
                } catch (NumberFormatException e) {
                }

                try {
                    int b = Integer.parseInt(box);
                    int c = Integer.parseInt(column);
                    goods.setBox(b);
                    goods.setColumn(c);
                } catch (NumberFormatException e) {
                    continue;
                }

                goodsList.add(goods);
                getLogger().i("goods code:" + goods.getBarCode() + " name:" + goods.getName() + " box:" + goods.getBox() + " column:" + goods.getColumn());
            }
        } catch (FileNotFoundException e) {
            getLogger().e("goods.xml not found");
            return false;
        } catch (ParserConfigurationException ex) {
            getLogger().e("goods.xml ParserConfigurationException:" + ex.toString());
            return false;
        } catch (IOException ex) {
            getLogger().e("goods.xml IOException:" + ex.toString());
            return false;
        } catch (SAXException ex) {
            getLogger().e("goods.xml SAXException:" + ex.toString());
            return false;
        }
        getLogger().d("goods count:" + goodsList.size());

//        loadGoodsDataBaseXML();
        return true;
    }

    private static void loadGoodsDataBaseXML() {
        clearGoodsDataBaseList();
        if (!loadGoodsDataBaseXML("file://" + Configure.path + "/" + DIRECTORY_CONFIG + "/" + FILE_GOODS_DATABASE)) {
            loadGoodsDataBaseXML("file://" + Configure.path + "/" + DIRECTORY_CONFIG + "/" + FILE_GOODS_DATABASE + "temp");
        }
        //转换排序用时时间
        sortByPinyin(goodsDataBaseList);
    }

    private static boolean loadGoodsDataBaseXML(String file) {
        getLogger().i("file path:"+file.toString());
        //实例化一个文档构建器工厂
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        try {
            //通过文档构建器工厂获取一个文档构建器
            DocumentBuilder db = dbf.newDocumentBuilder();
            //通过文档通过文档构建器构建一个文档实例
            Document doc = db.parse(file);
//            Document doc = db.parse("file://" + Configure.path + "/" + DIRECTORY_CONFIG + "/" + FILE_GOODS_DATABASE);
            NodeList nl1 = doc.getElementsByTagName("goods");
            if (nl1.getLength() == 0) {
                return false;
            }
            Node n1 = nl1.item(0);
            NodeList nl2 = n1.getChildNodes();
            if (nl2.getLength() == 0) {
                return false;
            }
            for (int i = 0; i < nl2.getLength(); i++) {
                Node n = nl2.item(i);
                if (!n.getNodeName().equals("item") || n.getNodeType() != Node.ELEMENT_NODE) {
                    continue;
                }
                NamedNodeMap map = n.getAttributes();
                if (map == null) {
                    continue;
                }
                Node NAME = map.getNamedItem("name");
                if (NAME == null) {
                    continue;
                }
                String name = NAME.getNodeValue();
                Node BC = map.getNamedItem("bc");
                if (BC == null) {
                    continue;
                }
                String bc = BC.getNodeValue();

                Node KIND = map.getNamedItem("kind");
                if (KIND == null) {
                    continue;
                }
                String kind = KIND.getNodeValue();

                GoodsModel goods = new GoodsModel();
                goods.setName(name);
                goods.setBarCode(bc != null ? bc : "");

                goods.setKind(kind != null ? kind : "0");
                addGoodsDataBaseList(goods);
            }
        } catch (FileNotFoundException e) {
            getLogger().e(file + " not found");
        } catch (ParserConfigurationException ex) {
            getLogger().e(file + " ParserConfigurationException:" + ex.toString());
        } catch (IOException ex) {
            getLogger().e( file + " IOException:" + ex.toString());
        } catch (SAXException ex) {
            getLogger().e( file + " SAXException:" + ex.toString());
        }
        return true;
    }

    /**
     * 清空商品库
     */
    public static void clearGoodsList() {
        synchronized (goodsListLock) {
            if (goodsList != null) {
                try {
                    goodsList.clear();
                } catch (ConcurrentModificationException e) {
                    getLogger().e("clearGoodsList:" + e.toString());
                }
            }
        }
    }

    /**
     * 添加商品
     *
     * @param model 商品
     */
    public static void addGoodsList(GoodsModel model) {
        synchronized (goodsListLock) {
            if (goodsList != null) {
                try {
                    goodsList.add(model);
                } catch (ConcurrentModificationException e) {
                    getLogger().e("addGoodsList:" + e.toString());
                }
            }
        }
    }

    /**
     * 获取商品库
     *
     * @return 商品库list
     */
    public static ArrayList<GoodsModel> getGoodsList() {
        synchronized (goodsListLock) {
            ArrayList<GoodsModel> newGoodsList = new ArrayList<>();
            if (goodsList != null) {
                try {
                    for (int i = 0; i < goodsList.size(); i++) {
                        newGoodsList.add(goodsList.get(i).clone());
                    }
                } catch (ConcurrentModificationException e) {
                    getLogger().e("getGoodsList:" + e.toString());
                }
            }
            return newGoodsList;
        }
    }

    /**
     * 更新商品XML文件，写入到文件中
     */
    public static void updateGoodsXML(ArrayList<GoodsModel> newGoodsList) {
        if (Configure.context == null || Configure.path == null) {
            return;
        }
        if (newGoodsList.size() == 0) {
            getLogger().i("newGoodsList size 0");
            return;
        }
        synchronized (goodsListLock) {
            if (goodsList == null) {
                return;
            }
            clearGoodsList();
            if (newGoodsList != null) {
                for (GoodsModel goodsModel : newGoodsList) {
                    goodsList.add(goodsModel.clone());
                }
            }
            if (goodsList.size() == 0) {
                getLogger().i("goodsList size 0");
                return;
            }

            String tempFile = Configure.path + "/" + DIRECTORY_CONFIG + "/" + FILE_GOODS + "temp";
//            File file = new File(Configure.path + "/" + DIRECTORY_CONFIG + "/" + FILE_GOODS);
            // 先将数据写入到临时文件中
            File file = new File(tempFile);
            BufferedWriter bw = null;
            try {
                if (!file.exists()) {
                    file.createNewFile();
                }
                bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file)));
                bw.write("<?xml version='1.0' encoding='UTF-8' standalone='yes' ?>");
                bw.write("<goods>");
                bw.flush();
                for (int i = 0; i < goodsList.size(); i++) {
                    GoodsModel model = goodsList.get(i);
//                    logger.i("updateGoodsXML goods name:"+model.getName());
                    bw.write("<item name=\"" + model.getName() + "\" code=\"" + model.getCode() + "\" image=\"" + model.getImage() + "\" type=\"" + model.getType() + "\" bc=\"" + model.getBarCode() + "\" discount=\"" + model.getDiscount() + "\" warranty=\"" + model.getWarranty() + "\" expiration=\"" + model.getExpiration() + "\" box=\"" + model.getBox() + "\" column=\"" + model.getColumn() + "\"/>");
                    bw.flush();
                }
                bw.write("</goods>");
                bw.flush();
            } catch (IOException e) {
                getLogger().e("updateGoodsXML:" + e.toString());
            } finally {
                if (bw != null) {
                    try {
                        bw.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    /**
     * 清空总库
     */
    private static void clearGoodsDataBaseList() {
        synchronized (goodsDataBaseListLock) {
            if (goodsDataBaseList != null) {
                goodsDataBaseList.clear();
            }
        }
    }

    /**
     * 添加总库商品
     *
     * @param model 商品
     */
    private static void addGoodsDataBaseList(GoodsModel model) {
        synchronized (goodsDataBaseListLock) {
            if (goodsDataBaseList != null) {
                goodsDataBaseList.add(model);
            }
        }
    }

    /**
     * 获取总库
     *
     * @return 商品总库list
     */
    public static ArrayList<GoodsModel> getGoodsDataBaseList() {
        synchronized (goodsDataBaseListLock) {
            ArrayList<GoodsModel> newGoodsList = new ArrayList<>();
            if (goodsDataBaseList != null) {
                for (GoodsModel goodsModel : goodsDataBaseList) {
                    String pinyin = goodsModel.pinyin;
                    if (pinyin == null || "".equals(pinyin)) {
                        pinyin = "#";
                    }
                    GoodsModel clone = goodsModel.clone();
                    clone.pinyin = pinyin;
                    newGoodsList.add(clone);
                }
            }
            return newGoodsList;
        }
    }

    /**
     * 更新商品总库XML文件，写入到文件中
     */
    public static void updateGoodsDatabaseXML(ArrayList<GoodsModel> newGoodsList) {
        getLogger().i("newGoodsList size:"+newGoodsList.size());
        if (Configure.context == null || Configure.path == null) {
            return;
        }
        if (newGoodsList.size() == 0) {
            return;
        }
        synchronized (goodsDataBaseListLock) {
            if (goodsDataBaseList == null) {
                return;
            }
            goodsDataBaseList.clear();
            sortByPinyin(newGoodsList);
            if (newGoodsList != null) {
                for (GoodsModel goodsModel : newGoodsList) {
                    String pinyin = goodsModel.pinyin;
                    if (pinyin == null || "".equals(pinyin)) {
                        pinyin = "#";
                    }
                    GoodsModel clone = goodsModel.clone();
                    clone.pinyin = pinyin;
                    goodsDataBaseList.add(clone);
                }
            }
            if (goodsDataBaseList.size() == 0) {
                getLogger().i("goodsDataBaseList size 0");
                return;
            }
//            File file = new File(Configure.path + "/" + DIRECTORY_CONFIG + "/" + FILE_GOODS_DATABASE);
            String tempFile = Configure.path + "/" + DIRECTORY_CONFIG + "/" + FILE_GOODS_DATABASE + "temp";
            String descFile = Configure.path + "/" + DIRECTORY_CONFIG + "/" + FILE_GOODS_DATABASE;
            File file = new File(tempFile);
            BufferedWriter bw = null;
            try {
                if (!file.exists()) {
                    file.createNewFile();
                }
                bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file)));
                bw.write("<?xml version='1.0' encoding='UTF-8' standalone='yes' ?>");
                bw.write("<goods>");
                bw.flush();
                for (GoodsModel model : goodsDataBaseList) {
                    bw.write("<item name=\"" + model.getName() + "\" bc=\"" + model.getBarCode() + "\" kind=\"" + model.getKind() + "\"/>");
                    bw.flush();
                }
                bw.write("</goods>");
                bw.flush();
            } catch (IOException e) {
                getLogger().e("updateGoodsDatabaseXML:" + e.toString());
            } finally {
                if (bw != null) {
                    try {
                        bw.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
            SystemClock.sleep(5);
            // 再覆盖真正的文件
            FileTools.copyFile(tempFile, descFile);
        }
    }

    /**
     * 检查goods.xml中的商品是否存在于goodsDatabase.xml中，不存在就删除
     */
    public static void checkGoodsInDatabase() {
        //检查商品库文件是否存在
        File file = new File(Configure.path + "/" + Configure.DIRECTORY_CONFIG + "/" + GoodsConfiguration.FILE_GOODS_DATABASE);
        if (!file.exists()) {
            //开启下载商品库线程
            DownloadGoodsDatabaseThread.getInstance().startDownload(DownloadGoodsDatabaseThread.TYPE_ALL);
        } else {
            //使用goodsDatabase.xml中的数据更新goods.xml中的商品
            getLogger().i("使用goodsDatabase.xml中的数据更新goods.xml中的商品");
            ArrayList<GoodsModel> deleteGoodsList = new ArrayList<>();
            ArrayList<GoodsModel> goodsList = GoodsConfiguration.getGoodsList();
            ArrayList<GoodsModel> goodsDataBaseList = GoodsConfiguration.getGoodsDataBaseList();
            for (int i = 0; i < goodsList.size(); i++) {
                GoodsModel model = goodsList.get(i);
                boolean isFind = false;
                for (int j = 0; j < goodsDataBaseList.size(); j++) {
                    GoodsModel goods = goodsDataBaseList.get(j);
                    if (goods.getBarCode().equals(model.getBarCode())) {
                        model.setName(goods.getName());
                        isFind = true;
                        break;
                    }
                }
                if (!isFind) {
                    //加到要删除的列表中
                    deleteGoodsList.add(model);
                    getLogger().i("goods.xml中需要删除的商品:" + model.toString());
                }
            }
            //从goods.xml中删除这个商品
            if (deleteGoodsList.size() > 0) {
                getLogger().i("goods.xml中存在" + deleteGoodsList.size() + "个需要删除的商品");
                goodsList.removeAll(deleteGoodsList);
//                for(int i=0;i<goodsList.size();i++){
//                    getLogger().i("goodsList goods name:" + goodsList.get(i).getName());
//                }
                //更新goods.xml
                GoodsConfiguration.updateGoodsXML(goodsList);
            }
        }
    }

    /**
     * 根据商品汉字拼音从a-z排序
     *
     * @param newGoodsList 要排序的list
     */
    private static void sortByPinyin(ArrayList<GoodsModel> newGoodsList) {
        try{
            if (newGoodsList != null) {
                // 根据商品库商品名称拼音a-z进行排序源数据

                Collections.sort(newGoodsList, new Comparator<GoodsModel>() {
                    @Override
                    public int compare(GoodsModel gm1, GoodsModel gm2) {
                        String pinyin1 = PinYinUtils.getInstance().getSelling(gm1.getName()).toUpperCase();
                        String pinyin2 = PinYinUtils.getInstance().getSelling(gm2.getName()).toUpperCase();
                        if (pinyin1.equals("UNKNOWN")) {
                            gm1.pinyin = "#";
                        } else {
                            gm1.pinyin = pinyin1;
                        }
                        if (pinyin2.equals("UNKNOWN")) {
                            gm2.pinyin = "#";
                        } else {
                            gm2.pinyin = pinyin2;
                        }
                        return pinyin1.compareTo(pinyin2);
                    }
                });
            }
        }catch(ArrayIndexOutOfBoundsException e){
            e.printStackTrace();
            getLogger().i("pinyin exception e:"+e.getMessage());
        }
    }
}
